using System;
using System.Configuration;
using System.Windows.Forms;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Win;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using WorkFlowDemo.Module;
using DevExpress.ExpressApp.Workflow.Server;
using DevExpress.ExpressApp.Workflow.CommonServices;
using DevExpress.ExpressApp.Workflow.Xpo;
using DevExpress.ExpressApp.Workflow.Versioning;

namespace WorkFlowDemo.Win
{
    public class WorkflowServerStarter : MarshalByRefObject
    {
        private static WorkflowServerStarter starter;
        private WorkflowServer server;
        private AppDomain domain;

        public void Start_(string connectionString, string applicationName)
        {
            ServerApplication serverApplication = new ServerApplication();
            serverApplication.ApplicationName = applicationName;
            serverApplication.Modules.Add(new WorkFlowDemoModule());
            serverApplication.ConnectionString = connectionString;
            serverApplication.Setup();
            serverApplication.Logon();

            IObjectSpaceProvider objectSpaceProvider = serverApplication.ObjectSpaceProvider;

            server = new WorkflowServer("http://localhost:19170", objectSpaceProvider, objectSpaceProvider);
            server.WorkflowDefinitionProvider = new WorkflowVersionedDefinitionProvider<XpoWorkflowDefinition, XpoUserActivityVersion>(objectSpaceProvider, null);
            server.StartWorkflowListenerService.DelayPeriod = TimeSpan.FromSeconds(5);
            server.StartWorkflowByRequestService.DelayPeriod = TimeSpan.FromSeconds(5);
            server.RefreshWorkflowDefinitionsService.DelayPeriod = TimeSpan.FromSeconds(600);
            server.CustomizeHost += delegate(object sender, CustomizeHostEventArgs e)
            {
                e.WorkflowInstanceStoreBehavior.WorkflowInstanceStore.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(2);
            };

            server.Start();
        }

        public void Stop_ ()
        {
            server.Stop();
        }

        public void Start (string connectionString, string applicationName)
        {
            try
            {
                domain = AppDomain.CreateDomain("ServerDomain");
                starter = (WorkflowServerStarter)domain.CreateInstanceAndUnwrap(System.Reflection.Assembly.GetEntryAssembly().FullName, typeof(WorkflowServerStarter).FullName);
                starter.OnCustomHandleException_ += new EventHandler<ExceptionEventArgs>(starter_OnCustomHandleException_);
                starter.Start_(connectionString, applicationName);
            }
            catch (Exception e)
            {
                Tracing.Tracer.LogError(e);
                if (OnCustomHandleException != null)
                {
                    OnCustomHandleException(null, new ExceptionEventArgs("Exception occurs: \r\n\r\n" + e.Message));
                }
            }
        }

        void starter_OnCustomHandleException_(object sender, ExceptionEventArgs e)
        {
            if (OnCustomHandleException != null)
            {
                OnCustomHandleException(null, e);
            }
        }

        public void Stop ( )
        {
            if (starter != null)
            {
                starter.Stop_();
            }
            if (domain != null)
            {
                AppDomain.Unload(domain);
            }
        }

        public event EventHandler<ExceptionEventArgs> OnCustomHandleException_;
        public event EventHandler<ExceptionEventArgs> OnCustomHandleException;
    }
}